//-----------------------------------------------------------------------------
//	File: usart.c
//	Author: hsia
//		bsp of usart2
//-----------------------------------------------------------------------------

#include "usart2.h"

#define BAUDRATE	562500

//-----------------------------------------------------------------------------
//	usart NVIC configure
//-----------------------------------------------------------------------------
static void configure_usart_nvic(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;

	// enable the usart interrupt
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

//-----------------------------------------------------------------------------
//	usart dma configure
//-----------------------------------------------------------------------------
static void configure_usart_dma(void)
{
	DMA_InitTypeDef		DMA_InitStructure;

	// Enable the peripheral's clock
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	// DMA Channel Tx Config
	DMA_DeInit(DMA1_Channel7);
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART2->DR);
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel7, &DMA_InitStructure);
}

//-----------------------------------------------------------------------------
//	usart module configure
//-----------------------------------------------------------------------------
static void configure_usart_module(void)
{
	USART_InitTypeDef	USART_InitStructure;

	// Enable the peripheral's clock
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	// USART configuration
	USART_InitStructure.USART_BaudRate = BAUDRATE;
	USART_InitStructure.USART_WordLength = USART_WordLength_9b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl =
		USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART2, &USART_InitStructure);
	// Enable USART DMA Tx & Rx request
	USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);
	// Enable USART's interrupt
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
	// Enable USART
//	USART_Cmd(USART2, ENABLE);
}

//-----------------------------------------------------------------------------
//	usart GPIO configure
//-----------------------------------------------------------------------------
static void configure_usart_gpio(void)
{
	GPIO_InitTypeDef	GPIO_InitStructure;

	// Enable the peripheral's clock
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	// Set USART's Tx
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	// Set USART's Rx
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

//-----------------------------------------------------------------------------
//	usart init
//-----------------------------------------------------------------------------
void usart2_init(void)
{
	configure_usart_nvic();
	configure_usart_dma();
	configure_usart_module();
	configure_usart_gpio();
}

//-----------------------------------------------------------------------------
//	usart2 baudrate
//-----------------------------------------------------------------------------
void usart2_baudrate(uint32_t bd)
{
	USART2->BRR = (uint16_t)((36000000 + (bd >> 1)) / bd);
}

//-----------------------------------------------------------------------------
//	usart dma tx configure
//-----------------------------------------------------------------------------
void usart2_dma_send(const void *buf, uint16_t len)
{
	// wait send ok
	if (DMA1_Channel7->CCR & DMA_CCR1_EN) {
		// wait send ok
		while ((DMA1->ISR & DMA1_IT_TC7) == 0);
		// stop dma
		DMA1_Channel7->CCR &= ~DMA_CCR1_EN;
		// clear send ok flag
		DMA1->IFCR = DMA1_IT_TC7;
	}
	// DMA Channel Tx memory base address
	DMA1_Channel7->CMAR = (uint32_t)buf;
	// DMA Channel Tx buffer length
	DMA1_Channel7->CNDTR = len;
	// Enable DMA_Channel Tx
	DMA1_Channel7->CCR |= DMA_CCR1_EN;
}

//-----------------------------------------------------------------------------
//	usart_send - Transmits single data through the USART
// 		@data: the data to transmit.
//-----------------------------------------------------------------------------
void usart2_send(uint16_t dat)
{
	while (!(USART2->SR & USART_FLAG_TXE));
	// Transmit Data
	USART2->DR = (dat & (uint16_t)0x01FF);
}

//-----------------------------------------------------------------------------
//	usart_receive - Returns the most recent received data by the USART
// 		@return: The received data.
//-----------------------------------------------------------------------------
uint16_t usart2_receive(void)
{
	// Receive Data
	return (uint16_t)(USART2->DR & (uint16_t)0x01FF);
}

